import { defineStore } from 'pinia'
import { login, getAuthUrl, loginByLLTCode, loginByOpenId } from '@/api/user'

// 本地缓存 key 常量
const USER_KEY = 'zqt:userInfo'
const TOKEN_KEY = 'token'
const CODE_CACHE_KEY = 'zqt:loginCode'
const CODE_CACHE_TIME_KEY = 'zqt:loginCodeTime'
const CODE_EXPIRE_MS = 10 * 60 * 1000 // 10分钟
let _ensurePromise = null // 并发登录控制

export const useUserStore = defineStore('user', {
	state: () => ({
		userInfo: null,
		token: localStorage.getItem(TOKEN_KEY) || '',
		isLoggedIn: false,
		code: localStorage.getItem(CODE_CACHE_KEY) || '',
		codeTime: Number(localStorage.getItem(CODE_CACHE_TIME_KEY) || 0),
	}),

	getters: {
		// 获取用户名
		username: (state) => state.userInfo?.username || '',
		// 获取用户头像
		avatar: (state) => state.userInfo?.avatar || '',
		// 检查是否已登录
		isAuthenticated: (state) => !!state.token && state.isLoggedIn,
		// code 是否有效
		isCodeValid: (state) => {
			if (!state.code) return false
			return Date.now() - state.codeTime < CODE_EXPIRE_MS
		},
	},

	actions: {
		// 从本地缓存恢复用户和 code
		loadFromCache() {
			if (!this.userInfo) {
				try {
					const raw = localStorage.getItem(USER_KEY)
					if (raw) {
						this.userInfo = JSON.parse(raw)
						this.isLoggedIn = !!this.userInfo?.userId
					}
				} catch (e) {
					console.error('解析缓存用户信息失败', e)
					localStorage.removeItem(USER_KEY)
				}
			}
			if (!this.token) {
				const t = localStorage.getItem(TOKEN_KEY)
				if (t) this.token = t
			}
			this.code = localStorage.getItem(CODE_CACHE_KEY) || ''
			this.codeTime = Number(localStorage.getItem(CODE_CACHE_TIME_KEY) || 0)
		},

		// 设置用户信息并写入缓存，同时缓存 code
		setUserInfo(userInfo) {
			this.userInfo = userInfo
			this.isLoggedIn = !!userInfo?.userId
			try {
				localStorage.setItem(USER_KEY, JSON.stringify(userInfo))
			} catch (e) {
				console.error('写入用户缓存失败', e)
			}
			// 缓存 code 及时间
			if (userInfo?.code) {
				this.code = userInfo.code
				this.codeTime = Date.now()
				localStorage.setItem(CODE_CACHE_KEY, userInfo.code)
				localStorage.setItem(CODE_CACHE_TIME_KEY, String(this.codeTime))
			}
		},

		// 设置 token 并写入缓存
		setToken(token) {
			this.token = token
			if (token) {
				localStorage.setItem(TOKEN_KEY, token)
			}
		},

		// 获取OAuth2授权URL
		async getOAuthUrl() {
			try {
				const res = await getAuthUrl()
				if (res.code === '0' && res.data) {
					return res.data
				}
				throw new Error(res.msg || '获取授权地址失败')
			} catch (error) {
				console.error('获取OAuth2授权URL失败:', error)
				throw error
			}
		},

		// 通过LLT Code登录
		async loginWithCode(code) {
			try {
				const res = await loginByLLTCode(code)
				if (res.code === '0' && res.data) {
					this.setToken(res.data.token)
					this.setUserInfo(res.data)
					return { success: true, data: res.data }
				} else if (['50001', '50002', '50003'].includes(res.code)) {
					// 返回特殊状态码，需要特殊处理
					// 先手动缓存 code（因为 res.data 中不包含 code）
					this.code = code
					this.codeTime = Date.now()
					localStorage.setItem(CODE_CACHE_KEY, code)
					localStorage.setItem(CODE_CACHE_TIME_KEY, String(this.codeTime))
					console.log('✅ 已缓存 code，供后续使用:', code.substring(0, 10) + '...')

					// 再设置用户信息（不设置 token）
					this.setUserInfo(res.data)
					this.setToken('')

					return { success: false, code: res.code, msg: res.msg, data: res.data }
				} else {
					throw new Error(res.msg || '登录失败')
				}
			} catch (error) {
				console.error('Code登录失败:', error)
				return { success: false, error: error.message }
			}
		},
		async loginWithOpenid(openid) {
			try {
				const res = await loginByOpenId(openid)
				if (res.code === '0' && res.data) {
					this.setToken(res.data.token)
					this.setUserInfo(res.data)
					return { success: true, data: res.data }
				} else if (['50001', '50002', '50003'].includes(res.code)) {
					// 返回特殊状态码，需要特殊处理
					// 注意：openid 登录没有 code，所以不缓存 code
					// 直接设置用户信息（不设置 token）
					this.setUserInfo(res.data)
					this.setToken('')

					return { success: false, code: res.code, msg: res.msg, data: res.data }
				} else {
					throw new Error(res.msg || '登录失败')
				}
			} catch (error) {
				console.error('Openid登录失败:', error)
				return { success: false, error: error.message }
			}
		},

		// 处理OAuth登录逻辑
		async handleOAuthLogin() {
			// 检查URL中是否有code参数
			const urlParams = new URLSearchParams(window.location.search)
			const code = urlParams.get('code')

			if (code) {
				// 如果有code，尝试登录
				const result = await this.loginWithCode(code)

				// 清除URL中的code参数
				const newUrl = new URL(window.location.href)
				newUrl.searchParams.delete('code')
				window.history.replaceState({}, document.title, newUrl.toString())

				return result
			}

			return null
		},

		// 确保已登录：优先用缓存 code 登录，code 2分钟内有效，过期需重新授权
		async ensureLogin() {
			this.loadFromCache()
			if (this.token && this.userInfo) return this.userInfo
			if (_ensurePromise) return _ensurePromise

			// 优先用缓存 code 登录
			if (this.code && Date.now() - this.codeTime < CODE_EXPIRE_MS) {
				_ensurePromise = (async () => {
					try {
						const result = await this.loginWithCode(this.code)
						if (result.success) {
							return result.data
						} else if (['50001', '50002', '50003'].includes(result.code)) {
							// 仍未绑定，返回 userInfo，供后续绑定后重试
							return this.userInfo
						} else {
							throw new Error(result.msg || '登录失败')
						}
					} catch (e) {
						console.error('自动 code 登录失败', e)
						throw e
					} finally {
						_ensurePromise = null
					}
				})()
				return _ensurePromise
			} else {
				// code 过期，需重新授权
				this.clearCodeCache()
				throw new Error('code已过期，请重新授权')
			}
		},

		// 清除 code 缓存
		clearCodeCache() {
			this.code = ''
			this.codeTime = 0
			localStorage.removeItem(CODE_CACHE_KEY)
			localStorage.removeItem(CODE_CACHE_TIME_KEY)
		},

		// 跳转到OAuth授权页面
		async redirectToAuth() {
			try {
				const authUrl = await this.getOAuthUrl()
				console.log('Redirecting to OAuth URL:', authUrl)
				window.location.href = authUrl
			} catch (error) {
				console.error('跳转授权页面失败:', error)
				throw error
			}
		},

		// 退出登录
		logout() {
			this.userInfo = null
			this.token = ''
			this.isLoggedIn = false
			this.clearCodeCache()
			localStorage.removeItem(USER_KEY)
			localStorage.removeItem(TOKEN_KEY)
		},
	},
})
